{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "245c0aa70db77606",
   "metadata": {},
   "source": [
    "# Azure Cosmos DB Mongo vCore\n",
    "\n",
    "This notebook shows you how to leverage this integrated [vector database](https://learn.microsoft.com/en-us/azure/cosmos-db/vector-database) to store documents in collections, create indicies and perform vector search queries using approximate nearest neighbor algorithms such as COS (cosine distance), L2 (Euclidean distance), and IP (inner product) to locate documents close to the query vectors. \n",
    "    \n",
    "Azure Cosmos DB is the database that powers OpenAI's ChatGPT service. It offers single-digit millisecond response times, automatic and instant scalability, along with guaranteed speed at any scale. \n",
    "\n",
    "Azure Cosmos DB for MongoDB vCore(https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/) provides developers with a fully managed MongoDB-compatible database service for building modern applications with a familiar architecture. You can apply your MongoDB experience and continue to use your favorite MongoDB drivers, SDKs, and tools by pointing your application to the API for MongoDB vCore account's connection string.\n",
    "\n",
    "[Sign Up](https://azure.microsoft.com/en-us/free/) for lifetime free access to get started today.\n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c493e205ce1dda5",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ab8e45f5bd435ade",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:25:05.278480Z",
     "start_time": "2024-02-08T18:24:51.560677Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.3.2\u001b[0m\r\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\r\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install --upgrade --quiet  pymongo langchain-openai langchain-community"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9c7ce9e7b26efbb0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:25:56.926147Z",
     "start_time": "2024-02-08T18:25:56.900087Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "CONNECTION_STRING = \"YOUR_CONNECTION_STRING\"\n",
    "INDEX_NAME = \"izzy-test-index\"\n",
    "NAMESPACE = \"izzy_test_db.izzy_test_collection\"\n",
    "DB_NAME, COLLECTION_NAME = NAMESPACE.split(\".\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2e66b097c6ce2e3",
   "metadata": {},
   "source": [
    "We want to use `OpenAIEmbeddings` so we need to set up our Azure OpenAI API Key alongside other environment variables. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4a052d99c6b8a2a7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:26:06.558294Z",
     "start_time": "2024-02-08T18:26:06.550008Z"
    }
   },
   "outputs": [],
   "source": [
    "# Set up the OpenAI Environment Variables\n",
    "os.environ[\"OPENAI_API_TYPE\"] = \"azure\"\n",
    "os.environ[\"OPENAI_API_VERSION\"] = \"2023-05-15\"\n",
    "os.environ[\"OPENAI_API_BASE\"] = (\n",
    "    \"YOUR_OPEN_AI_ENDPOINT\"  # https://example.openai.azure.com/\n",
    ")\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"YOUR_OPENAI_API_KEY\"\n",
    "os.environ[\"OPENAI_EMBEDDINGS_DEPLOYMENT\"] = (\n",
    "    \"smart-agent-embedding-ada\"  # the deployment name for the embedding model\n",
    ")\n",
    "os.environ[\"OPENAI_EMBEDDINGS_MODEL_NAME\"] = \"text-embedding-ada-002\"  # the model name"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebaa28c6e2b35063",
   "metadata": {},
   "source": [
    "Now, we need to load the documents into the collection, create the index and then run our queries against the index to retrieve matches.\n",
    "\n",
    "Please refer to the [documentation](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/vector-search) if you have questions about certain parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "183741cf8f4c7c53",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:27:00.782280Z",
     "start_time": "2024-02-08T18:26:47.339151Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_community.document_loaders import TextLoader\n",
    "from langchain_community.vectorstores.azure_cosmos_db import (\n",
    "    AzureCosmosDBVectorSearch,\n",
    "    CosmosDBSimilarityType,\n",
    "    CosmosDBVectorSearchType,\n",
    ")\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "from langchain_text_splitters import CharacterTextSplitter\n",
    "\n",
    "SOURCE_FILE_NAME = \"../../how_to/state_of_the_union.txt\"\n",
    "\n",
    "loader = TextLoader(SOURCE_FILE_NAME)\n",
    "documents = loader.load()\n",
    "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n",
    "docs = text_splitter.split_documents(documents)\n",
    "\n",
    "# OpenAI Settings\n",
    "model_deployment = os.getenv(\n",
    "    \"OPENAI_EMBEDDINGS_DEPLOYMENT\", \"smart-agent-embedding-ada\"\n",
    ")\n",
    "model_name = os.getenv(\"OPENAI_EMBEDDINGS_MODEL_NAME\", \"text-embedding-ada-002\")\n",
    "\n",
    "\n",
    "openai_embeddings: OpenAIEmbeddings = OpenAIEmbeddings(\n",
    "    deployment=model_deployment, model=model_name, chunk_size=1\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "39ae6058c2f7fdf1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:31:13.486173Z",
     "start_time": "2024-02-08T18:30:54.175890Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'raw': {'defaultShard': {'numIndexesBefore': 1,\n",
       "   'numIndexesAfter': 2,\n",
       "   'createdCollectionAutomatically': False,\n",
       "   'ok': 1}},\n",
       " 'ok': 1}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pymongo import MongoClient\n",
    "\n",
    "# INDEX_NAME = \"izzy-test-index-2\"\n",
    "# NAMESPACE = \"izzy_test_db.izzy_test_collection\"\n",
    "# DB_NAME, COLLECTION_NAME = NAMESPACE.split(\".\")\n",
    "\n",
    "client: MongoClient = MongoClient(CONNECTION_STRING)\n",
    "collection = client[DB_NAME][COLLECTION_NAME]\n",
    "\n",
    "model_deployment = os.getenv(\n",
    "    \"OPENAI_EMBEDDINGS_DEPLOYMENT\", \"smart-agent-embedding-ada\"\n",
    ")\n",
    "model_name = os.getenv(\"OPENAI_EMBEDDINGS_MODEL_NAME\", \"text-embedding-ada-002\")\n",
    "\n",
    "vectorstore = AzureCosmosDBVectorSearch.from_documents(\n",
    "    docs,\n",
    "    openai_embeddings,\n",
    "    collection=collection,\n",
    "    index_name=INDEX_NAME,\n",
    ")\n",
    "\n",
    "# Read more about these variables in detail here. https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/vector-search\n",
    "num_lists = 100\n",
    "dimensions = 1536\n",
    "similarity_algorithm = CosmosDBSimilarityType.COS\n",
    "kind = CosmosDBVectorSearchType.VECTOR_IVF\n",
    "m = 16\n",
    "ef_construction = 64\n",
    "ef_search = 40\n",
    "score_threshold = 0.1\n",
    "\n",
    "vectorstore.create_index(\n",
    "    num_lists, dimensions, similarity_algorithm, kind, m, ef_construction\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "32c68d3246adc21f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:31:47.468902Z",
     "start_time": "2024-02-08T18:31:46.053602Z"
    }
   },
   "outputs": [],
   "source": [
    "# perform a similarity search between the embedding of the query and the embeddings of the documents\n",
    "query = \"What did the president say about Ketanji Brown Jackson\"\n",
    "docs = vectorstore.similarity_search(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8feeeb4364efb204",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:31:50.982598Z",
     "start_time": "2024-02-08T18:31:50.977605Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. \n",
      "\n",
      "Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n",
      "\n",
      "One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n",
      "\n",
      "And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence.\n"
     ]
    }
   ],
   "source": [
    "print(docs[0].page_content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37e4df8c7d7db851",
   "metadata": {},
   "source": [
    "Once the documents have been loaded and the index has been created, you can now instantiate the vector store directly and run queries against the index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "3c218ab6f59301f7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:32:14.299599Z",
     "start_time": "2024-02-08T18:32:12.923464Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. \n",
      "\n",
      "Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n",
      "\n",
      "One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n",
      "\n",
      "And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence.\n"
     ]
    }
   ],
   "source": [
    "vectorstore = AzureCosmosDBVectorSearch.from_connection_string(\n",
    "    CONNECTION_STRING, NAMESPACE, openai_embeddings, index_name=INDEX_NAME\n",
    ")\n",
    "\n",
    "# perform a similarity search between a query and the ingested documents\n",
    "query = \"What did the president say about Ketanji Brown Jackson\"\n",
    "docs = vectorstore.similarity_search(query)\n",
    "\n",
    "print(docs[0].page_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "fd67e4d92c9ab32f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-02-08T18:32:24.021434Z",
     "start_time": "2024-02-08T18:32:22.867658Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. \n",
      "\n",
      "Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n",
      "\n",
      "One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n",
      "\n",
      "And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence.\n"
     ]
    }
   ],
   "source": [
    "vectorstore = AzureCosmosDBVectorSearch(\n",
    "    collection, openai_embeddings, index_name=INDEX_NAME\n",
    ")\n",
    "\n",
    "# perform a similarity search between a query and the ingested documents\n",
    "query = \"What did the president say about Ketanji Brown Jackson\"\n",
    "docs = vectorstore.similarity_search(query)\n",
    "\n",
    "print(docs[0].page_content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b63c73c7e905001c",
   "metadata": {},
   "source": [
    "## Filtered vector search (Preview)\n",
    "Azure Cosmos DB for MongoDB supports pre-filtering with $lt, $lte, $eq, $neq, $gte, $gt, $in, $nin, and $regex. To use this feature, enable \"filtering vector search\" in the \"Preview Features\" tab of your Azure Subscription. Learn more about preview features [here](https://learn.microsoft.com/azure/cosmos-db/mongodb/vcore/vector-search#filtered-vector-search-preview)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b63c73c7e905001c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
